package model.area_effect;

import model.core.GameScheduler;
import model.core.Logger;
import model.core.Notifiable;
import model.effects.Effect;
import model.entity.Entity;
import model.map.MapPoint;

/**
 * Defines the SkillObjects used to hold the abstraction of abilities.
 * @author Zachary
 */
public class SkillObject extends AreaOfEffect implements Notifiable, Cloneable{
	private Entity caster;
	private MapPoint origin;
	private MapPoint location;
	
	/**
	 * Constructor for SkillObjects.
	 * @param name
	 * @param graphicID
	 * @param effect
	 * @param mapLocation
	 * @param skillObjectID
	 * @param duration
	 * @param caster
	 * @param origin
	 */
	public SkillObject(String name, String graphicID, Effect effect, 
			Entity caster, MapPoint origin, MapPoint location) {
		super(name, graphicID, effect);
		this.caster = caster;
		this.origin = origin;
		this.location = location;
	}
	
	/**
	 * Apply the effect held by this SkillObject to the
	 * entity, remove the SkillObject from the scheduler, 
	 * and remove the SkillObject from the map.
	 */
	public void interact(Entity entity){
		this.getEffect().doEffect(entity);
		GameScheduler.getInstance().unRegister(this);
		AreaEffectRemover.getInstance().removeSkillObjectFromMap(this, location);
		
		int distance = MapPoint.findDistance(entity.getLocation(), caster.getLocation());
		
		// output to logger
		double test = 1 / (.3 * distance);
		double probability = Math.random();
		String casterName = this.caster.getName();
		String targetName = entity.getName();
		
		int passiveSkillLevel = caster.getObservationSkill();
		
		if(probability <= test)
			Logger.getInstance().writeToLogger(casterName +
					" hit enity " + targetName + ".  " + targetName +
					this.getEffect().toString(passiveSkillLevel));
		else
			Logger.getInstance().writeToLogger("Something happened, " +
					"but I couldn't really see it from here.");
	}
	
	/**
	 * Called when the scheduler executes this Notifiable.
	 * Removes the Skill Object from the map.
	 */
	public void execute() {
		GameScheduler.getInstance().unRegister(this);
		AreaEffectRemover.getInstance().removeSkillObjectFromMap(this, this.location);
	}
	
	/**
	 * Set the location of the SkillObject on the map.
	 * @param p
	 */
	public void setLocation(MapPoint p){
		this.location = p;
	}
	
	/**
	 * Return a clone of the SkillObject.
	 */
	public SkillObject clone(){
		try{
		      SkillObject cloned = (SkillObject)super.clone();
		      cloned.caster = this.caster;
		      cloned.origin = this.origin.clone();
		      return cloned;
	    }catch(CloneNotSupportedException e){
		      System.out.println(e);
		      return null;
	    }
	}
}
